package com.travel.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.travel.common.Result;
import com.travel.domain.entity.GuideDetail;
import com.travel.service.GuideDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.travel.constant.MessageConstant.CACHE_NULL;

@RestController
@RequestMapping("/guideDetail")
public class GuideDetailController {

    @Autowired
    private GuideDetailService guideDetailService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String ALL_GUIDE_DETAILS_CACHE_KEY = "guide:all";  // 所有攻略详情的缓存键
    private static final String GUIDE_BY_ID_CACHE_KEY = "guide:id:";        // 单个攻略详情的缓存键
    private static final String GUIDE_LIST_BY_ID_CACHE_KEY = "guide:list:id:";   // 单个景点攻略详情列表的缓存键

    private static final String GUIDE_FILTER_CACHE_KEY = "guide:filter:";   // 筛选后的攻略详情的缓存键
    private static final String CACHE_KEY_TOP15 = "guide:top15";  // 默认 15 条数据的缓存键

    /**
     * 获取所有攻略详情
     *
     * @return 所有 GuideDetail 的列表
     */
    @GetMapping("/all")
    public Result<List<GuideDetail>> getAllGuideDetails() {
        // 尝试从缓存中获取所有攻略详情
        List<GuideDetail> cachedGuideDetails = (List<GuideDetail>) redisTemplate.opsForValue().get(ALL_GUIDE_DETAILS_CACHE_KEY);

        if (cachedGuideDetails != null) {
            // 如果缓存中有数据，直接返回缓存数据
            return Result.success(cachedGuideDetails);
        }

        try {
            // 如果缓存中没有数据，则从数据库查询
            List<GuideDetail> guideDetails = guideDetailService.list();

            // 将查询结果存入缓存，并设置过期时间（如 10 分钟）
            redisTemplate.opsForValue().set(ALL_GUIDE_DETAILS_CACHE_KEY, guideDetails, 120, TimeUnit.MINUTES);

            return Result.success(guideDetails);
        } catch (Exception e) {
            return Result.error("获取所有攻略详情失败: " + e.getMessage());
        }
    }

    /**
     * 获取指定场景的攻略列表
     * @param scenarioId 场景 ID
     * @return 所有符合条件的攻略详情
     */
    @GetMapping("/getGuidesById/{scenarioId}")
    public Result<List<GuideDetail>> getGuideListById(@PathVariable Long scenarioId) {
        String cacheKey = GUIDE_LIST_BY_ID_CACHE_KEY  + scenarioId;

        // 尝试从缓存中获取指定场景的攻略详情
        List<GuideDetail> cachedGuideDetails = (List<GuideDetail>) redisTemplate.opsForValue().get(cacheKey);

        if (cachedGuideDetails != null) {
            // 如果缓存中有数据，直接返回缓存数据
            return Result.success(cachedGuideDetails);
        }

        try {
            // 如果缓存中没有数据，则从数据库查询
            LambdaQueryWrapper<GuideDetail> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(GuideDetail::getScenicId, scenarioId);
            List<GuideDetail> guideDetails = guideDetailService.list(wrapper);

            // 将查询结果存入缓存，并设置过期时间（如 10 分钟）
            redisTemplate.opsForValue().set(cacheKey, guideDetails, 120, TimeUnit.MINUTES);

            return Result.success(guideDetails);
        } catch (Exception e) {
            return Result.error("获取攻略详情失败: " + e.getMessage());
        }
    }

    /**
     * 获取单个攻略详情
     * @param guideDetailId 攻略详情 ID
     * @return 单个攻略详情
     */
    // 解决缓存穿透
    @GetMapping("/getGuideById/{guideDetailId}")
    public Result<GuideDetail> getGuideById(@PathVariable Long guideDetailId) {
        String cacheKey = GUIDE_BY_ID_CACHE_KEY + guideDetailId;

        // 尝试从缓存中获取单个攻略详情
        String cachedData = (String) redisTemplate.opsForValue().get(cacheKey);

        if (cachedData != null) {
            if (CACHE_NULL.equals(cachedData)) {
                // 如果缓存中是空结果标识，直接返回空数据
                return Result.success(null);
            } else {
                // 如果缓存中有数据，反序列化并返回数据
                GuideDetail cachedGuideDetail = JSON.parseObject(cachedData, GuideDetail.class);
                return Result.success(cachedGuideDetail);
            }
        }

        try {
            // 如果缓存中没有数据，则从数据库查询
            LambdaQueryWrapper<GuideDetail> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(GuideDetail::getId, guideDetailId);
            GuideDetail guideDetail = guideDetailService.getOne(wrapper);

            if (guideDetail != null) {
                // 数据存在，将查询结果序列化为 JSON 存入缓存，并设置过期时间（如 10 分钟）
                redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(guideDetail), 120, TimeUnit.MINUTES);
                return Result.success(guideDetail);
            } else {
                // 数据不存在，存入“空结果标识”，并设置短期过期时间（如 5 分钟）
                redisTemplate.opsForValue().set(cacheKey, CACHE_NULL, 5, TimeUnit.MINUTES);
                return Result.success(null);
            }
        } catch (Exception e) {
            return Result.error("获取单个攻略详情失败: " + e.getMessage());
        }
    }


    /**
     * 获取经过筛选的攻略详情
     * @param typeId 筛选类型 ID
     * @param areaId 筛选区域 ID
     * @param name 筛选名称
     * @return 筛选后的攻略详情
     */
    @GetMapping("/guide-filter")
    public Result<List<GuideDetail>> getScenicFilter(
            @RequestParam(required = false) Long typeId,   // 使用 typeId 进行筛选
            @RequestParam(required = false) Long areaId,    // 使用 areaId 进行筛选
            @RequestParam(required = false) String name      // 模糊查询名称
    ) {
        // 根据筛选条件构建一个唯一的缓存键
        String cacheKey = GUIDE_FILTER_CACHE_KEY + (typeId != null ? typeId : "null") + ":"
                + (areaId != null ? areaId : "null") + ":"
                + (name != null ? name : "null");

        try {
            // 尝试从缓存中获取数据
            List<GuideDetail> cachedList = (List<GuideDetail>) redisTemplate.opsForValue().get(cacheKey);
            if (cachedList != null) {
                // 如果缓存中有数据，直接返回缓存数据
                return Result.success(cachedList);
            }

            // 如果没有任何筛选条件，返回默认的15条数据
            if (typeId == null && areaId == null && (name == null || name.isEmpty())) {
                // 检查默认的 15 条数据是否已缓存
                List<GuideDetail> top15 = (List<GuideDetail>) redisTemplate.opsForValue().get(CACHE_KEY_TOP15);
                if (top15 != null) {
                    // 如果缓存中有默认的 15 条数据，直接返回缓存数据
                    return Result.success(top15);
                }

                // 如果缓存中没有默认 15 条数据，则从数据库查询
                top15 = guideDetailService.getTop15ByDistance();
                // 将查询结果存入缓存，并设置过期时间（如 10 分钟）
                redisTemplate.opsForValue().set(CACHE_KEY_TOP15, top15, 120, TimeUnit.MINUTES);
                return Result.success(top15);
            }

            // 否则进行筛选
            List<GuideDetail> filteredList = guideDetailService.filterScenicProfiles(typeId, areaId, name);
            // 将查询结果存入缓存，并设置过期时间（如 10 分钟）
            redisTemplate.opsForValue().set(cacheKey, filteredList, 120, TimeUnit.MINUTES);
            return Result.success(filteredList);

        } catch (Exception e) {
            // 捕获异常并返回统一的错误响应
            return Result.error("服务器内部错误：" + e.getMessage());
        }
    }
}
